<%#
 Copyright 2013-2018 the original author or authors from the JHipster project.

 This file is part of the JHipster project, see https://www.jhipster.tech/
 for more information.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-%>
import axios from 'axios';
<%_ if (authenticationType === 'jwt') { _%>
import { Storage } from 'react-jhipster';
<%_ } _%>

import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
<% if (enableTranslation) { %>import { setLocale } from 'app/shared/reducers/locale';<% } %>

export const ACTION_TYPES = {
  <%_ if (authenticationType !== 'oauth2') { _%>
  LOGIN: 'authentication/LOGIN',
  <%_ } _%>
  GET_SESSION: 'authentication/GET_SESSION',
  LOGOUT: 'authentication/LOGOUT',
  CLEAR_AUTH: 'authentication/CLEAR_AUTH',
  ERROR_MESSAGE: 'authentication/ERROR_MESSAGE'
};

<%_ if (authenticationType === 'jwt') { _%>
const AUTH_TOKEN_KEY = 'jhi-authenticationToken';
<%_ } _%>

const initialState = {
  loading: false,
  isAuthenticated: false,
  <%_ if (authenticationType !== 'oauth2') { _%>
  loginSuccess: false,
  loginError: false, // Errors returned from server side
  showModalLogin: false,
  <%_ } _%>
  account: {} as any,
  errorMessage: null as string, // Errors returned from server side
  redirectMessage: null as string,
  sessionHasBeenFetched: false
};

export type AuthenticationState =  Readonly<typeof initialState>;

// Reducer

export default (state: AuthenticationState = initialState, action): AuthenticationState => {
  switch (action.type) {
    <%_ if (authenticationType !== 'oauth2') { _%>
    case REQUEST(ACTION_TYPES.LOGIN):
    <%_ } _%>
    case REQUEST(ACTION_TYPES.GET_SESSION):
      return {
        ...state,
        loading: true
      };
    <%_ if (authenticationType !== 'oauth2') { _%>
    case FAILURE(ACTION_TYPES.LOGIN):
      return {
        ...initialState,
        errorMessage: action.payload,
        showModalLogin: true,
        loginError: true
      };
    <%_ } _%>
    case FAILURE(ACTION_TYPES.GET_SESSION):
      return {
        ...state,
        loading: false,
        isAuthenticated: false,
        sessionHasBeenFetched: true,
      <%_ if (authenticationType !== 'oauth2') { _%>
        showModalLogin: true,
      <%_ } _%>
        errorMessage: action.payload
      };
    <%_ if (authenticationType !== 'oauth2') { _%>
    case SUCCESS(ACTION_TYPES.LOGIN):
      return {
        ...state,
        loading: false,
        loginError: false,
        showModalLogin: false,
        loginSuccess: true
      };
    <%_ } _%>
    case ACTION_TYPES.LOGOUT:
      return {
        ...initialState,
      <%_ if (authenticationType !== 'oauth2') { _%>
        showModalLogin: true
      <%_ } _%>
      };
    case SUCCESS(ACTION_TYPES.GET_SESSION):
      {
        const isAuthenticated = action.payload && action.payload.data && action.payload.data.activated;
        return {
          ...state,
          isAuthenticated,
          loading: false,
          sessionHasBeenFetched: true,
          account: action.payload.data
        };
      }
    case ACTION_TYPES.ERROR_MESSAGE:
      return {
        ...initialState,
      <%_ if (authenticationType !== 'oauth2') { _%>
        showModalLogin: true,
      <%_ } _%>
        redirectMessage: action.message
      };
    case ACTION_TYPES.CLEAR_AUTH:
      return {
        ...state,
        loading: false,
      <%_ if (authenticationType !== 'oauth2') { _%>
        showModalLogin: true,
      <%_ } _%>
        isAuthenticated: false
      };
    default:
      return state;
  }
};

export const displayAuthError = message => ({ type: ACTION_TYPES.ERROR_MESSAGE, message });

export const getSession = () => dispatch => dispatch({
  type: ACTION_TYPES.GET_SESSION,
  payload: axios.get('<%= apiUaaPath %>api/account')
});

<%_ if (authenticationType === 'session') { _%>
export const login = (username, password, rememberMe = false) => async (dispatch, getState) => {
  const data = `j_username=${encodeURIComponent(username)}&j_password=${encodeURIComponent(password)}&remember-me=${rememberMe}&submit=Login`;
  await dispatch({
    type: ACTION_TYPES.LOGIN,
    payload: axios.post('api/authentication', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
  });
 <%_ if (enableTranslation) { _%>
  await dispatch(getSession());

  const account = getState().authentication.account;
  if (account && account.langKey) {
    dispatch(setLocale(account.langKey));
  }
  <%_ } else { _%>
  dispatch(getSession());
  <%_ } _%>
};
<%_ } else if (authenticationType === 'jwt') { _%>
export const login = (username, password, rememberMe = false) => async (dispatch, getState) => {
  const result = await dispatch({
    type: ACTION_TYPES.LOGIN,
    payload: axios.post('api/authenticate', { username, password, rememberMe })
  });
  const bearerToken = result.value.headers.authorization;
  if (bearerToken && bearerToken.slice(0, 7) === 'Bearer ') {
    const jwt = bearerToken.slice(7, bearerToken.length);
    if (rememberMe) {
      Storage.local.set(AUTH_TOKEN_KEY, jwt);
    } else {
      Storage.session.set(AUTH_TOKEN_KEY, jwt);
    }
  }
 <%_ if (enableTranslation) { _%>
  await dispatch(getSession());

  const account = getState().authentication.account;
  if (account && account.langKey) {
    await dispatch(setLocale(account.langKey));
  }
  <%_ } else { _%>
  dispatch(getSession());
  <%_ } _%>
};
<%_ } else if (authenticationType === 'uaa') { _%>
export const login = (username, password, rememberMe = false) => async (dispatch, getState) => {
  const result = await dispatch({
    type: ACTION_TYPES.LOGIN,
    payload: axios.post('auth/login', { username, password })
  });
 <%_ if (enableTranslation) { _%>
  await dispatch(getSession());

  const account = getState().authentication.account;
  if (account && account.langKey) {
    await dispatch(setLocale(account.langKey));
  }
  <%_ } else { _%>
  dispatch(getSession());
  <%_ } _%>
};
<%_ } _%>

<%_ if (authenticationType === 'jwt') { _%>
export const clearAuthToken = () => {
  if (Storage.local.get(AUTH_TOKEN_KEY)) {
    Storage.local.remove(AUTH_TOKEN_KEY);
  }
  if (Storage.session.get(AUTH_TOKEN_KEY)) {
    Storage.session.remove(AUTH_TOKEN_KEY);
  }
};

export const logout = () => dispatch => {
  clearAuthToken();
  dispatch({
    type: ACTION_TYPES.LOGOUT
  });
};
<%_ } else if (authenticationType === 'uaa') { _%>
export const logout = () => async dispatch => {
  await dispatch({
    type: ACTION_TYPES.LOGOUT,
    payload: axios.post('auth/logout', {})
  });
  dispatch(getSession());
};
<%_ } else { _%>
export const logout = () => async dispatch => {
  await dispatch({
    type: ACTION_TYPES.LOGOUT,
    payload: axios.post('api/logout', {})
  });
  dispatch(getSession());
};
<%_ } _%>

export const clearAuthentication = messageKey => (dispatch, getState) => {
  <%_ if (authenticationType == 'jwt') { _%>
  clearAuthToken();
  <%_ } _%>
  dispatch(displayAuthError(messageKey));
  dispatch({
    type: ACTION_TYPES.CLEAR_AUTH
  });
};
